package com.mind.core.net.msg;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.mind.core.net.model.IConnector;


/**
 * IMessageBase的基本实现
 * 
 * 
 * 
 * @param <T>
 */
public abstract class BaseMessage<T extends IConnector> implements Message {

	/** 与该消息绑定的ByteBuffer,用于read或者write方法的操作对象 * */
	protected ByteBuf buf;

	/** 消息的长度 * */
	private short messageLength;

	/** 消息的类型 * */
	protected short messageType;
	/** 消息的名称 * */
	private String name;
	protected IConnector sender;
	protected BaseMessage() {
	}
	public void setSender(IConnector player){
		this.sender=player;
	}
	public IConnector sender(){
		return sender;
	}
	
	/**
	 * 将该消息的属性写入到当前设置的ByteBuffer中,按以下顺序写入:
	 * 
	 * <pre>
	 * 1.消息长度(占位符0,实际的长度当writeImpl写完之后再确定)
	 * 2.消息类型
	 * 3.消息体 
	 * 4.如果第3步成功,则修正消息长度,并返回true 
	 * 5.如果第3步失败,则返回flase
	 * </pre>
	 * 
	 * @return true,写入成功;false,写入失败
	 * @throws MessageParseException
	 *             在写入的过程中发生错误时抛出此异常
	 */
	public boolean write() throws MessageParseException {
		try {
			int _op = buf.writerIndex();
			writeShort((short)0);
			writeShort(getMessageType());
			boolean b = writeImpl();
			if (!b) {
				return false;
			}
			// 消息体写完之后,修正消息头中的长度字段
			final int _length = (buf.writerIndex() - _op);
			messageLength = (short) _length;			
			if(_length > Short.MAX_VALUE){
				throw new IllegalArgumentException(
						"The message length is not invalid,value ["
								+ _length + "],maybe it's too long?"+this.getMessageName());
			
			}
			buf.setShort(_op,messageLength);
			return true;
		} catch (Exception e) {
			throw new MessageParseException(e);
		}
	}
	public void setType(short type){
		this.messageType=type;
	}
	/**
	 * 将当前buf中的数据读取到IBaseMessage对象对应的属性中
	 * 
	 * @return true,读取成功;false,读取失败
	 * @throws MessageParseException
	 *             在读取过程发生错误的抛出此异常
	 */
	public boolean read() throws MessageParseException {
		try {
			this.buf.readerIndex(0);
			messageLength = readShort();
			messageType=readShort();
			return readImpl();
		} catch (Exception e) {			
			throw new MessageParseException(e+" Type:"+this.messageType);
		}
	}

	/**
	 * 取得消息的当前长度
	 * 
	 * @return -1,该消息还未与ByteBuffer绑定;否则返回ByteBuffer的位置
	 */
	public final int getLength() {
		return this.messageLength;
	}

	protected final void setLength(short length) {
		this.messageLength = length;
	}
	@Override
	public String getMessageName() {
		return this.name;
	}

	public void setTypeName(String typeName) {
		this.name = typeName;
	}

	/**
	 * 使用IMessageBase.ENCODE_MESSAGE_LENGTH作为缓存区初始化的大小
	 */
	@Override
	public int getInitBufferLength() {
		return Message.ENCODE_MESSAGE_LENGTH;
	}

	protected void writeByte(byte data) {
		buf.writeByte( data);
	}

	protected void writeShort(short data) {
		buf.writeShort(data);
	}

	protected void writeInteger(int data) {
		buf.writeInt(data);
	}

	protected void writeInteger(float data) {
		buf.writeInt((int) (data + 0.5));
	}

	protected void writeLong(long data) {
		buf.writeLong(data);
	}

	protected void writeDate(Date data) {
		if (data != null) {
			buf.writeLong(data.getTime());
		} else {
			buf.writeLong(0L);
		}

	}

	protected void writeFloat(float data) {
		buf.writeFloat(data);
	}

	protected void writeDouble(double data) {
		buf.writeDouble(data);
	}

	protected void writeBytes(byte[] data) {
		buf.writeBytes(data);
	}

	protected void writeString(String str) {
		writeString(str, DEFAULT_CHARSET);
	}

	protected void writeShorts(short[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			buf.writeShort(data[i]);
		}
	}

	protected void writeIntegers(int[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			buf.writeInt(data[i]);
		}
	}

	protected void writeLongs(long[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			buf.writeLong(data[i]);
		}
	}

	protected void writeDates(Date[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			if (data != null) {
				buf.writeLong(data[i].getTime());
			} else {
				buf.writeLong(0L);
			}
		}
		

	}
	protected void writeFloats(float[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			buf.writeFloat(data[i]);
		}
	}

	protected void writeDoubles(double[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			buf.writeDouble(data[i]);
		}
	}
	protected void writeStrings(String[] data) {
		buf.writeShort(data.length);
		for(int i=0;i<data.length;i++){
			writeString(data[i], DEFAULT_CHARSET);
		}
	}
	protected void writeString(String str, String charset) {
		try {
			if (str == null) {
				buf.writeShort(0);
				return;
			}
			byte[] bytes = str.getBytes(charset);
			buf.writeShort(bytes.length);
			buf.writeBytes(bytes);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 将msg,消息包体数据写入的该消息的ByteBuffer数据缓存中
	 * 
	 * @param msg
	 * @throws MessageParseException
	 */
	protected void writeMessage(Message msg) {
		ByteBuf _buf=Unpooled.buffer(msg.getInitBufferLength());
		msg.setBuffer(_buf);
		msg.writeImpl();
		this.buf.writeBytes(_buf);
		msg.setBuffer(null);
		_buf.clear();
	}

	/**
	 * 
	 * @param length
	 * @param handlerType
	 * @param msg
	 * @return 
	 * @throws MessageParseException
	 */
	protected void readMessage(Message msg) {
		msg.setBuffer(this.buf);
		msg.readImpl();
		msg.setBuffer(null);
	}
	protected byte readByte() {
		return buf.readByte();
	}

	protected short readShort() {
		return buf.readShort();
	}

	protected int readInteger() {
		return buf.readInt();
	}

	protected long readLong() {
		return buf.readLong();
	}

	protected Date readDate() {
		long time = buf.readLong();
		if (time > 0) {
			return new Date(time);
		} else {
			return null;
		}
	}

	protected float readFloat() {
		return buf.readFloat();
	}

	protected double readDouble() {
		return buf.readDouble();
	}

	protected void readBytes(byte[] bytes) {
		buf.readBytes(bytes);
	}

	protected String readString() {
		return readString(DEFAULT_CHARSET);
	}
	protected short[] readShorts() {
		short[] result=new short[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readShort();
		}
		return result;
	}

	protected int[] readIntegers() {
		int[] result=new int[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readInteger();
		}
		return result;
	}

	protected long[] readLongs() {
		long[] result=new long[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readLong();
		}
		return result;
	}

	protected Date[] readDates() {
		Date[] result=new Date[buf.readShort()];
		for(int i=0;i<result.length;i++){
			long time = buf.readLong();
			if (time > 0) {
				result[i]= new Date(time);
			} else {
				result[i]= null;
			}
		}
		return result;
	}

	protected float[] readFloats() {
		float[] result=new float[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readFloat();
		}
		return result;
	}

	protected double[] readDoubles() {
		double[] result=new double[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readDouble();
		}
		return result;
	}
	protected String[] readStrings() {
		String[] result=new String[buf.readShort()];
		for(int i=0;i<result.length;i++){
			result[i]=readString(DEFAULT_CHARSET);
		}
		return result;
	}
	protected String readString(String charset) {
		short len = buf.readShort();
		byte[] bytes = new byte[len];
		buf.readBytes(bytes);
		try {
			return new String(bytes, charset);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return "";
		}
	}

	/**
	 * 根据当前buf的位置,修正消息头的长度字段
	 * 
	 * @throws IllegalArgumentException
	 *             如果消息的长度超出了short的最大值(65535),或者为0则会抛出此异常
	 */
	protected void fixHeaderLength() {
	}

	/**
	 * 设置该消息当前操作的ByteBuffer,即BaseMessage的read是从buf中读取数据,而write是将数据写入到buf中
	 * 
	 * @param buf
	 */
	public void setBuffer(ByteBuf buf) {
		this.buf = buf;
	}

     /**
	 * 获取当前Buff，用于在其他Util类中直接对Buff进行写操作
	 * 
	 * @param buf
	 */
	@Override
	public ByteBuf getBuffer() {
		return this.buf;
	}

	private final static Map<String, Boolean> excludes = new HashMap<String, Boolean>();
	static {
		excludes.put("buf", Boolean.TRUE);
	}

}